import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { CalendarModule } from './calendar.module';
import { LvCalendarEvents } from '../core/types';

@Component({
  template: `
    <lv-calendar
      [(ngModel)]="date"
      [lvCalendarMode]="calendarMode"
      [lvCalendarTitleReadonly]="titleReadonly"
      [lvOnlyShowActiveCell]="showActiveCell"
      (lvActiveDateChange)="activeDateChange()"
      (lvCalendarModeChange)="calendarModeChange()"
      [lvCalendarEvents]="events"
    ></lv-calendar>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
class TestCalendarComponent {
  calendarMode = 'month';
  titleReadonly = true;
  showActiveCell = false;

  date: Date = new Date(2022, 3, 18);
  events: LvCalendarEvents[] = [
    {
      id: 1,
      title: '江苏紫金银行客户满意活动1',
      startDate: new Date(2022, 3, 1),
      endDate: new Date(2022, 3, 2),
    },
    {
      id: 2,
      title: '江苏紫金银行客户满意活动2',
      startDate: new Date(2022, 3, 1),
    },
    {
      id: 3,
      title: '江苏紫金银行活动3',
      startDate: new Date(2022, 3, 30),
      endDate: new Date(2022, 4, 2),
      type: 3,
    },
  ];

  activeDateChange() {}
  calendarModeChange() {}
}

describe('CalendarComponent', () => {
  beforeEach(
    waitForAsync(() => {
      TestBed.configureTestingModule({
        declarations: [TestCalendarComponent],
        imports: [CalendarModule, FormsModule, NoopAnimationsModule],
        teardown: { destroyAfterEach: false },
      }).compileComponents();
    })
  );

  describe('render', () => {
    let component: TestCalendarComponent;
    let fixture: ComponentFixture<TestCalendarComponent>;
    const renderComp = fakeAsync(para => {
      for (const [key, value] of Object.entries(para)) {
        component[key] = value;
      }
      fixture.detectChanges();
      tick(1500);
      fixture.detectChanges();
      expect(fixture).toMatchSnapshot();
      tick(1500);
    });

    beforeEach(() => {
      fixture = TestBed.createComponent(TestCalendarComponent);
      component = fixture.componentInstance;
    });

    it('with lvCalendarMode', () => {
      renderComp({ calendarMode: 'year' });
    });

    it('with lvOnlyShowActiveCell', () => {
      renderComp({ showActiveCell: true });
    });
  });

  describe('work', () => {
    let component: TestCalendarComponent;
    let fixture: ComponentFixture<TestCalendarComponent>;

    beforeEach(fakeAsync(() => {
      fixture = TestBed.createComponent(TestCalendarComponent);
      component = fixture.componentInstance;
      fixture.detectChanges();
      tick(500);
    }));

    // 点击从月切换到年显示，lvCalendarModeChange触发
    it('should work with lvCalendarModeChange', fakeAsync(() => {
      jest.spyOn(component, 'calendarModeChange');
      const year = fixture.nativeElement.querySelectorAll('lv-radio')[1];
      const title = fixture.nativeElement.querySelector('.lv-canlendar-header-center');
      expect(title.textContent).toContain('月');

      year.dispatchEvent(new Event('click'));
      fixture.detectChanges();
      tick(1500);
      fixture.detectChanges();
      tick(1500);
      expect(title.textContent).not.toContain('月');
      expect(component.calendarModeChange).toBeCalled();
    }));

    // 点击能选中
    it('should work when click', fakeAsync(() => {
      const day = fixture.nativeElement.querySelectorAll('li')[15];
      day.dispatchEvent(new Event('click'));
      fixture.detectChanges();
      tick(1500);
      fixture.detectChanges();
      tick(1500);
      expect(day.classList).toContain('lv-calendar-selected-day');
    }));

    // 可点击下拉选择年份日月，或点击左右切换年份日月，触发lvActiveDateChange回调
    it('should work when select', fakeAsync(() => {
      jest.spyOn(component, 'activeDateChange');
      component.titleReadonly = false;
      fixture.detectChanges();
      tick(1500);

      // 点击弹出选择年月下拉面板
      const center = fixture.nativeElement.querySelector('.center');
      center.dispatchEvent(new Event('click'));
      fixture.detectChanges();
      tick(1500);

      // 选择年
      const year = document.querySelector('.lv-calendar-panel-year');
      const firstYear = year.querySelector('li');
      const selectedYear = firstYear.textContent.trim();
      firstYear.dispatchEvent(new Event('click'));
      fixture.detectChanges();
      tick(1500);

      // 点击外部确定选择
      center.dispatchEvent(new Event('click'));
      fixture.detectChanges();
      tick(1500);
      expect(center.textContent).toContain(selectedYear);
      expect(component.activeDateChange).toBeCalledTimes(1);

      // 点击<<按钮切换年份生效
      const doublePrev = fixture.nativeElement.querySelector('.lv-icon-host');
      doublePrev.dispatchEvent(new Event('click'));
      fixture.detectChanges();
      tick(1500);
      const expectYear = (Number(selectedYear) - 1).toString();
      expect(center.textContent).toContain(expectYear);
      expect(component.activeDateChange).toBeCalledTimes(2);
    }));
  });
});
